package tunnel

import (
	"context"
	"fmt"
	"log"
	"net"
	"sync"
	"sync/atomic"
	"time"

	"internal-net-bridge-server/internal/tunnel/protocols/common"

	"github.com/google/uuid"
)

// ============================================================================
// 隧道连接池 - 多隧道连接管理
// ============================================================================
//
// 核心功能：
// - 管理多个隧道连接（TunnelConnection）
// - 负载均衡（智能选择最优连接）
// - 健康检查和自动重连
// - 动态扩展/收缩连接池
//
// 使用场景：
// - 大文件传输不阻塞小文件
// - 并发请求并行处理
// - 提高吞吐量和响应速度
//
// ============================================================================

// TunnelPool 隧道连接池
type TunnelPool struct {
	tunnelID    string              // 隧道ID
	connections []*TunnelConnection // 连接池（所有连接）
	minSize     int                 // 最小连接数（默认3）
	maxSize     int                 // 最大连接数（默认10）

	// 负载均衡
	balancer *LoadBalancer // 负载均衡器

	// 🔥🔥🔥 客户端连接亲和性（浏览器连接 → 隧道连接）
	// 核心思路：一个浏览器TCP连接固定使用一个隧道连接
	// 优点：稳定、不跳隧道、通用（不区分Range/非Range）
	clientConnMap   map[string]*TunnelConnection // 浏览器连接地址 -> 隧道连接
	clientConnMutex sync.RWMutex                 // 保护客户端连接映射

	// ⚠️ 旧的请求队列已删除（改用QUIC）
	// requestQueue        *RequestQueue // 请求优先级队列
	requestQueueEnabled bool // 是否启用请求队列（默认false）

	// 🔥 流量控制（商业级特性）
	trafficConfig         common.TrafficConfig // 流量控制配置
	trafficControlEnabled bool                 // 是否启用流量控制（默认true）

	// 🔥 协议帧化（实验性特性）
	frameProtocolEnabled bool   // 是否启用协议帧化（默认false，实验性）
	protocolVersion      string // 协议版本（v1=旧协议，v2=帧协议）

	// 连接管理
	mutex sync.RWMutex // 保护连接池

	// 统计信息
	totalRequests  int64 // 总请求数
	activeRequests int64 // 活跃请求数

	// 健康检查
	healthCheckInterval time.Duration // 健康检查间隔（默认30秒）
	healthCheckEnabled  bool          // 是否启用健康检查
	lastPoolSize        int           // 上次检查的连接池大小（用于去重警告）
	lastWarningTime     time.Time     // 上次警告时间（用于限制警告频率）

	// 生命周期
	closed   bool          // 是否已关闭
	stopChan chan struct{} // 停止信号
}

// TunnelConnection 单个隧道连接
type TunnelConnection struct {
	id             string    // 连接ID
	conn           net.Conn  // TCP连接
	isHealthy      bool      // 健康状态
	activeRequests int32     // 当前活跃请求数（原子操作）
	totalRequests  int64     // 总请求数
	lastUsed       time.Time // 最后使用时间
	createdAt      time.Time // 创建时间
	lastError      error     // 最后错误
	failureCount   int       // 连续失败次数

	// 性能统计
	totalBytes    int64         // 总传输字节数
	totalDuration time.Duration // 总处理时长

	mutex sync.RWMutex // 保护连接状态
}

// BalancingStrategy 负载均衡策略
type BalancingStrategy int

const (
	RoundRobin       BalancingStrategy = iota // 轮询
	LeastConnections                          // 最少连接数
	WeightedRandom                            // 加权随机
	SmartSelection                            // 智能选择（推荐）
)

// LoadBalancer 负载均衡器
type LoadBalancer struct {
	strategy           BalancingStrategy            // 均衡策略
	pool               *TunnelPool                  // 关联的连接池
	roundRobinIndex    int32                        // 轮询索引
	largeFileThreshold int64                        // 大文件阈值（默认10MB）
	urlAffinity        map[string]*TunnelConnection // 🔥 URL亲和性映射（用于Range请求）
	affinityMutex      sync.RWMutex                 // 保护亲和性映射的锁
}

// ============================================================================
// TunnelPool 方法
// ============================================================================

// NewTunnelPool 创建隧道连接池
func NewTunnelPool(tunnelID string, minSize, maxSize int) *TunnelPool {
	if minSize <= 0 {
		minSize = 3 // 默认最小3个连接
	}
	if maxSize <= 0 {
		maxSize = 10 // 默认最大10个连接
	}
	if maxSize < minSize {
		maxSize = minSize
	}

	pool := &TunnelPool{
		tunnelID:    tunnelID,
		connections: make([]*TunnelConnection, 0, maxSize),
		minSize:     minSize,
		maxSize:     maxSize,
		// 🔥🔥🔥 移除idleConnsChan（对象池遗留代码，已切换到多路复用模式）
		// idleConnsChan:         make(chan *TunnelConnection, maxSize),
		clientConnMap:         make(map[string]*TunnelConnection), // 🔥 客户端连接亲和性映射（可选）
		healthCheckInterval:   30 * time.Second,
		healthCheckEnabled:    true,
		requestQueueEnabled:   false,                          // 🚀 优化：禁用队列，直接分发
		trafficControlEnabled: false,                          // 🚀 优化：禁用限速，让OS处理
		trafficConfig:         common.AggressiveTrafficConfig, // 保留配置（但不启用）
		frameProtocolEnabled:  false,                          // 🔥 默认禁用协议帧化（实验性）
		protocolVersion:       "v1",                           // 🔥 默认使用v1协议（向后兼容）
		stopChan:              make(chan struct{}),
	}

	// 创建负载均衡器
	pool.balancer = &LoadBalancer{
		strategy:           SmartSelection, // 默认使用智能选择
		pool:               pool,
		largeFileThreshold: 10 * 1024 * 1024,                   // 10MB
		urlAffinity:        make(map[string]*TunnelConnection), // 🔥 URL亲和性映射
	}

	// 🔥 启动URL亲和性清理协程（定期清理不再使用的映射）
	go pool.balancer.cleanupURLAffinity(pool.stopChan)

	// ⚠️ 旧的请求队列已删除（改用QUIC）
	// if pool.requestQueueEnabled {
	// 	pool.requestQueue = NewRequestQueue(pool)
	// }

	// 🔥 日志：显示启用的商业级特性
	features := []string{}
	if pool.requestQueueEnabled {
		features = append(features, "优先级队列")
	}
	if pool.trafficControlEnabled {
		features = append(features, "流量控制")
	}

	if len(features) > 0 {
		log.Printf("✅ 创建隧道连接池（商业级）: tunnelID=%s, minSize=%d, maxSize=%d", tunnelID, minSize, maxSize)
		log.Printf("   🎯 启用特性: %v", features)
		if pool.trafficControlEnabled {
			log.Printf("   🚦 流量限制: 小请求=不限速, 中等=%dMB/s, 大请求=%dMB/s",
				pool.trafficConfig.MediumRequestLimit/(1024*1024),
				pool.trafficConfig.LargeRequestLimit/(1024*1024))
		}
	} else {
		log.Printf("✅ 创建隧道连接池: tunnelID=%s, minSize=%d, maxSize=%d", tunnelID, minSize, maxSize)
	}

	return pool
}

// AddConnection 添加连接到连接池
func (tp *TunnelPool) AddConnection(conn net.Conn) (*TunnelConnection, error) {
	tp.mutex.Lock()
	defer tp.mutex.Unlock()

	if tp.closed {
		return nil, fmt.Errorf("连接池已关闭")
	}

	// 检查连接池是否已满
	if len(tp.connections) >= tp.maxSize {
		return nil, fmt.Errorf("连接池已满: 当前=%d, 最大=%d", len(tp.connections), tp.maxSize)
	}

	// 创建新连接
	tunnelConn := &TunnelConnection{
		id:        uuid.New().String(),
		conn:      conn,
		isHealthy: true,
		createdAt: time.Now(),
		lastUsed:  time.Now(),
	}

	tp.connections = append(tp.connections, tunnelConn)

	log.Printf("✅ [连接池:%s] 添加隧道连接: connID=%s, 连接池大小=%d/%d",
		tp.tunnelID, tunnelConn.id, len(tp.connections), tp.maxSize)

	return tunnelConn, nil
}

// RemoveConnection 从连接池移除连接
func (tp *TunnelPool) RemoveConnection(connID string) {
	tp.mutex.Lock()
	defer tp.mutex.Unlock()

	for i, conn := range tp.connections {
		if conn.id == connID {
			// 关闭连接
			if conn.conn != nil {
				conn.conn.Close()
			}

			// 从切片中移除
			tp.connections = append(tp.connections[:i], tp.connections[i+1:]...)

			log.Printf("➖ 移除隧道连接: tunnelID=%s, connID=%s, 连接池大小=%d/%d",
				tp.tunnelID, connID, len(tp.connections), tp.maxSize)
			return
		}
	}
}

// RemoveConnectionByConn 通过net.Conn移除连接
func (tp *TunnelPool) RemoveConnectionByConn(targetConn net.Conn) {
	tp.mutex.Lock()
	defer tp.mutex.Unlock()

	for i, conn := range tp.connections {
		if conn.conn == targetConn {
			// 不重复关闭连接（调用方会关闭）
			// 从切片中移除
			tp.connections = append(tp.connections[:i], tp.connections[i+1:]...)

			log.Printf("➖ 移除隧道连接: tunnelID=%s, connID=%s, 连接池大小=%d/%d",
				tp.tunnelID, conn.id, len(tp.connections), tp.maxSize)
			return
		}
	}
}

// SelectConnection 选择最优连接（多路复用模式）
// 参数:
//   - requestSize: 请求大小（估算值，可选）
//   - isStreaming: 是否为流式传输
func (tp *TunnelPool) SelectConnection(requestSize int64, isStreaming bool) *TunnelConnection {
	return tp.balancer.Select(requestSize, isStreaming)
}

// SelectConnectionWithQueue 通过负载均衡选择连接（多路复用模式）
// 参数:
//   - requestID: 请求ID
//   - method: HTTP方法
//   - path: 请求路径
//   - headers: 请求头
//   - requestSize: 请求大小
//   - isStreaming: 是否为流式传输
//   - ctx: 请求上下文（用于取消）
//   - timeout: 超时时间
//
// 返回:
//   - *TunnelConnection: 选中的连接
//   - error: 错误信息（无可用连接）
func (tp *TunnelPool) SelectConnectionWithQueue(
	requestID string,
	method string,
	path string,
	headers map[string][]string,
	requestSize int64,
	isStreaming bool,
	ctx context.Context,
	timeout time.Duration,
) (*TunnelConnection, error) {
	// 🔥🔥🔥 多路复用模式：使用负载均衡器选择最优连接
	conn := tp.balancer.Select(requestSize, isStreaming)
	if conn == nil {
		return nil, fmt.Errorf("[负载均衡] 没有可用隧道")
	}
	return conn, nil
}

// GetConnection 根据ID获取连接
func (tp *TunnelPool) GetConnection(connID string) *TunnelConnection {
	tp.mutex.RLock()
	defer tp.mutex.RUnlock()

	for _, conn := range tp.connections {
		if conn.id == connID {
			return conn
		}
	}
	return nil
}

// GetAllConnections 获取所有连接
func (tp *TunnelPool) GetAllConnections() []*TunnelConnection {
	tp.mutex.RLock()
	defer tp.mutex.RUnlock()

	// 返回副本，避免外部修改
	result := make([]*TunnelConnection, len(tp.connections))
	copy(result, tp.connections)
	return result
}

// Size 获取连接池大小
func (tp *TunnelPool) Size() int {
	tp.mutex.RLock()
	defer tp.mutex.RUnlock()
	return len(tp.connections)
}

// GetRateLimiter 根据请求大小获取速率限制器（商业级特性）
//
// 参数：
//   - requestSize: 请求大小（字节）
//
// 返回：
//   - *common.RateLimiter: 速率限制器（如果未启用流量控制则返回不限速的限制器）
func (tp *TunnelPool) GetRateLimiter(requestSize int64) *common.RateLimiter {
	if !tp.trafficControlEnabled {
		// 未启用流量控制，返回不限速的限制器
		return common.NewRateLimiter("不限速", 0)
	}

	return common.CreateRateLimiterForRequest(requestSize, tp.trafficConfig)
}

// SetTrafficConfig 动态调整流量控制配置
//
// 参数：
//   - config: 新的流量控制配置
func (tp *TunnelPool) SetTrafficConfig(config common.TrafficConfig) {
	tp.mutex.Lock()
	defer tp.mutex.Unlock()

	tp.trafficConfig = config
	log.Printf("🚦 更新流量控制配置: tunnelID=%s", tp.tunnelID)
	log.Printf("   ├─ 小请求限速: %d MB/s", config.SmallRequestLimit/(1024*1024))
	log.Printf("   ├─ 中等请求限速: %d MB/s", config.MediumRequestLimit/(1024*1024))
	log.Printf("   └─ 大请求限速: %d MB/s", config.LargeRequestLimit/(1024*1024))
}

// HealthySize 获取健康连接数量
func (tp *TunnelPool) HealthySize() int {
	tp.mutex.RLock()
	defer tp.mutex.RUnlock()

	count := 0
	for _, conn := range tp.connections {
		conn.mutex.RLock()
		if conn.isHealthy {
			count++
		}
		conn.mutex.RUnlock()
	}
	return count
}

// StartHealthCheck 启动健康检查
func (tp *TunnelPool) StartHealthCheck() {
	if !tp.healthCheckEnabled {
		return
	}

	go func() {
		ticker := time.NewTicker(tp.healthCheckInterval)
		defer ticker.Stop()

		log.Printf("🏥 启动健康检查: tunnelID=%s, 间隔=%v", tp.tunnelID, tp.healthCheckInterval)

		for {
			select {
			case <-ticker.C:
				tp.performHealthCheck()
			case <-tp.stopChan:
				log.Printf("🏥 停止健康检查: tunnelID=%s", tp.tunnelID)
				return
			}
		}
	}()
}

// performHealthCheck 执行健康检查
func (tp *TunnelPool) performHealthCheck() {
	tp.mutex.RLock()
	connections := make([]*TunnelConnection, len(tp.connections))
	copy(connections, tp.connections)
	tp.mutex.RUnlock()

	for _, conn := range connections {
		// 检查连接是否健康
		healthy := tp.checkConnectionHealth(conn)

		conn.mutex.Lock()
		wasHealthy := conn.isHealthy
		conn.isHealthy = healthy

		if !healthy {
			conn.failureCount++
			if conn.failureCount >= 3 {
				// 连续3次失败，标记为不健康并移除
				log.Printf("❌ 连接不健康: tunnelID=%s, connID=%s, 连续失败=%d次",
					tp.tunnelID, conn.id, conn.failureCount)
				conn.mutex.Unlock()

				// 移除不健康的连接
				tp.RemoveConnection(conn.id)
				continue
			}
		} else {
			conn.failureCount = 0
			if !wasHealthy {
				log.Printf("✅ 连接恢复健康: tunnelID=%s, connID=%s", tp.tunnelID, conn.id)
			}
		}
		conn.mutex.Unlock()
	}

	// 🔥 优化：智能警告去重，避免日志刷屏
	currentSize := tp.Size()
	if currentSize < tp.minSize {
		now := time.Now()

		// 只在连接池大小变化或距离上次警告超过5分钟时才打印
		sizeChanged := currentSize != tp.lastPoolSize
		timeElapsed := now.Sub(tp.lastWarningTime) > 5*time.Minute

		if sizeChanged || timeElapsed {
			if currentSize == 0 {
				log.Printf("⚠️ 连接池为空: tunnelID=%s", tp.tunnelID)
				log.Printf("💡 可能原因:")
				log.Printf("   1. 客户端未启动或已断开")
				log.Printf("   2. 网络连接问题")
				log.Printf("   3. 客户端配置的连接池大小为0")
				log.Printf("💡 建议: 检查客户端连接状态")
			} else {
				log.Printf("⚠️ 连接池大小不足: tunnelID=%s, 当前=%d, 最小=%d, 健康=%d",
					tp.tunnelID, currentSize, tp.minSize, tp.healthyConnections())
				log.Printf("💡 建议: 客户端可能需要增加连接池大小或检查网络稳定性")
			}

			tp.lastPoolSize = currentSize
			tp.lastWarningTime = now
		}
	} else {
		// 连接池恢复正常，重置状态
		if tp.lastPoolSize < tp.minSize && currentSize >= tp.minSize {
			log.Printf("✅ 连接池恢复正常: tunnelID=%s, 当前=%d, 健康=%d",
				tp.tunnelID, currentSize, tp.healthyConnections())
		}
		tp.lastPoolSize = currentSize
	}
}

// healthyConnections 返回健康连接数
func (tp *TunnelPool) healthyConnections() int {
	count := 0
	for _, conn := range tp.connections {
		conn.mutex.RLock()
		if conn.isHealthy {
			count++
		}
		conn.mutex.RUnlock()
	}
	return count
}

// checkConnectionHealth 检查单个连接健康状态
func (tp *TunnelPool) checkConnectionHealth(conn *TunnelConnection) bool {
	conn.mutex.RLock()
	tcpConn := conn.conn
	lastUsed := conn.lastUsed
	conn.mutex.RUnlock()

	if tcpConn == nil {
		return false
	}

	// 检查空闲时间
	idleTime := time.Since(lastUsed)
	if idleTime > 5*time.Minute {
		// 空闲超过5分钟，发送心跳检测
		return tp.sendHeartbeat(tcpConn)
	}

	return true
}

// sendHeartbeat 发送心跳包
func (tp *TunnelPool) sendHeartbeat(conn net.Conn) bool {
	// 发送简单的心跳包: HEARTBEAT\r\n
	conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
	_, err := conn.Write([]byte("HEARTBEAT\r\n"))
	conn.SetWriteDeadline(time.Time{})

	return err == nil
}

// ============================================================================
// 🔥🔥🔥 客户端连接亲和性（浏览器连接 → 隧道连接）
// ============================================================================
//
// # GetOrAssignConnectionForClient 获取或分配隧道连接给客户端
//
// 核心思路：
//   - 一个浏览器TCP连接 → 固定使用一个隧道连接
//   - 不管是Range还是普通请求，只要来自同一个浏览器连接，就用同一个隧道
//   - 浏览器连接关闭时，才释放隧道
//
// 优点：
//
//	✅ 通用：不需要区分Range/非Range
//	✅ 稳定：不会跳隧道
//	✅ 简单：实现清晰，符合TCP语义
//	✅ 高效：一个连接就是一个会话
//
// ============================================================================
func (tp *TunnelPool) GetOrAssignConnectionForClient(clientAddr string, requestSize int64, isStreaming bool) *TunnelConnection {
	// 1. 先检查是否已有映射（快速路径，读锁）
	tp.clientConnMutex.RLock()
	if tunnelConn, exists := tp.clientConnMap[clientAddr]; exists {
		tp.clientConnMutex.RUnlock()

		// 检查隧道连接是否健康
		if tunnelConn.isHealthy {
			// 增加活跃请求计数
			tunnelConn.AcquireRequest()
			activeReqs := tunnelConn.GetActiveRequests()

			log.Printf("🔗 [客户端亲和性] 复用已分配隧道: clientAddr=%s, connID=%s, 活跃请求=%d",
				clientAddr, tunnelConn.id, activeReqs)

			return tunnelConn
		}

		// 隧道连接不健康，需要重新分配（写锁）
		log.Printf("⚠️  [客户端亲和性] 隧道连接不健康，重新分配: clientAddr=%s, 旧connID=%s",
			clientAddr, tunnelConn.id)
	} else {
		tp.clientConnMutex.RUnlock()
	}

	// 2. 需要分配新隧道（写锁）
	tp.clientConnMutex.Lock()
	defer tp.clientConnMutex.Unlock()

	// 再次检查（double-check locking）
	if tunnelConn, exists := tp.clientConnMap[clientAddr]; exists && tunnelConn.isHealthy {
		tunnelConn.AcquireRequest()
		activeReqs := tunnelConn.GetActiveRequests()

		log.Printf("🔗 [客户端亲和性] 复用已分配隧道（double-check）: clientAddr=%s, connID=%s, 活跃请求=%d",
			clientAddr, tunnelConn.id, activeReqs)

		return tunnelConn
	}

	// 3. 使用负载均衡器选择最优隧道
	tunnelConn := tp.balancer.Select(requestSize, isStreaming)
	if tunnelConn == nil {
		log.Printf("❌ [客户端亲和性] 没有可用隧道: clientAddr=%s", clientAddr)
		return nil
	}

	// 4. 保存映射
	tp.clientConnMap[clientAddr] = tunnelConn
	tunnelConn.AcquireRequest()
	activeReqs := tunnelConn.GetActiveRequests()

	log.Printf("🆕 [客户端亲和性] 分配新隧道: clientAddr=%s, connID=%s, 活跃请求=%d",
		clientAddr, tunnelConn.id, activeReqs)

	return tunnelConn
}

// ReleaseConnectionForClient 释放客户端的隧道连接
//
// 调用时机：当浏览器TCP连接关闭时
func (tp *TunnelPool) ReleaseConnectionForClient(clientAddr string) {
	tp.clientConnMutex.Lock()
	defer tp.clientConnMutex.Unlock()

	tunnelConn, exists := tp.clientConnMap[clientAddr]
	if !exists {
		// 没有映射，可能已经被清理了
		return
	}

	// 移除映射
	delete(tp.clientConnMap, clientAddr)

	// 获取活跃请求数（用于日志）
	activeReqs := tunnelConn.GetActiveRequests()

	log.Printf("🔓 [客户端亲和性] 释放隧道: clientAddr=%s, connID=%s, 剩余活跃请求=%d",
		clientAddr, tunnelConn.id, activeReqs)
}

// Close 关闭连接池
func (tp *TunnelPool) Close() {
	tp.mutex.Lock()
	defer tp.mutex.Unlock()

	if tp.closed {
		return
	}

	tp.closed = true
	close(tp.stopChan)

	// ⚠️ 旧的请求队列已删除
	// if tp.requestQueue != nil {
	// 	tp.requestQueue.Close()
	// }

	// 关闭所有连接
	for _, conn := range tp.connections {
		if conn.conn != nil {
			conn.conn.Close()
		}
	}

	tp.connections = nil

	log.Printf("🔌 关闭隧道连接池: tunnelID=%s", tp.tunnelID)
}

// GetStats 获取统计信息
func (tp *TunnelPool) GetStats() map[string]interface{} {
	tp.mutex.RLock()
	defer tp.mutex.RUnlock()

	stats := map[string]interface{}{
		"tunnelID":       tp.tunnelID,
		"poolSize":       len(tp.connections),
		"healthySize":    tp.HealthySize(),
		"minSize":        tp.minSize,
		"maxSize":        tp.maxSize,
		"totalRequests":  atomic.LoadInt64(&tp.totalRequests),
		"activeRequests": atomic.LoadInt64(&tp.activeRequests),
	}

	// 连接详情
	connections := make([]map[string]interface{}, 0, len(tp.connections))
	for _, conn := range tp.connections {
		conn.mutex.RLock()
		connStats := map[string]interface{}{
			"id":             conn.id,
			"isHealthy":      conn.isHealthy,
			"activeRequests": atomic.LoadInt32(&conn.activeRequests),
			"totalRequests":  conn.totalRequests,
			"totalBytes":     conn.totalBytes,
			"createdAt":      conn.createdAt,
			"lastUsed":       conn.lastUsed,
			"failureCount":   conn.failureCount,
		}
		conn.mutex.RUnlock()
		connections = append(connections, connStats)
	}
	stats["connections"] = connections

	return stats
}

// ============================================================================
// TunnelConnection 方法
// ============================================================================

// AcquireRequest 请求开始时调用
func (tc *TunnelConnection) AcquireRequest() {
	atomic.AddInt32(&tc.activeRequests, 1)
	tc.mutex.Lock()
	tc.totalRequests++
	tc.lastUsed = time.Now()
	tc.mutex.Unlock()
}

// ReleaseRequest 请求结束时调用
func (tc *TunnelConnection) ReleaseRequest(bytes int64, duration time.Duration) {
	atomic.AddInt32(&tc.activeRequests, -1)
	tc.mutex.Lock()
	tc.totalBytes += bytes
	tc.totalDuration += duration
	tc.lastUsed = time.Now()
	tc.mutex.Unlock()
}

// GetActiveRequests 获取活跃请求数
func (tc *TunnelConnection) GetActiveRequests() int {
	return int(atomic.LoadInt32(&tc.activeRequests))
}

// GetAvgLatency 获取平均延迟
func (tc *TunnelConnection) GetAvgLatency() time.Duration {
	tc.mutex.RLock()
	defer tc.mutex.RUnlock()

	if tc.totalRequests == 0 {
		return 0
	}
	return tc.totalDuration / time.Duration(tc.totalRequests)
}

// IsIdle 是否空闲
func (tc *TunnelConnection) IsIdle() bool {
	return atomic.LoadInt32(&tc.activeRequests) == 0
}

// Write 写入数据（包装）
func (tc *TunnelConnection) Write(data []byte) (int, error) {
	tc.mutex.RLock()
	conn := tc.conn
	tc.mutex.RUnlock()

	if conn == nil {
		return 0, fmt.Errorf("连接已关闭")
	}

	n, err := conn.Write(data)
	if err != nil {
		tc.mutex.Lock()
		tc.lastError = err
		tc.isHealthy = false
		tc.mutex.Unlock()
	}

	return n, err
}

// ============================================================================
// LoadBalancer 方法
// ============================================================================

// Select 选择最优连接（向后兼容，不支持URL亲和性）
func (lb *LoadBalancer) Select(requestSize int64, isStreaming bool) *TunnelConnection {
	return lb.SelectWithAffinity("", "", requestSize, isStreaming)
}

// SelectWithAffinity 选择最优连接（支持URL亲和性）
// 参数:
//   - url: 请求URL（用于Range请求的隧道亲和性）
//   - rangeHeader: Range请求头（如果存在）
//   - requestSize: 请求大小
//   - isStreaming: 是否为流式传输
//
// 返回:
//   - *TunnelConnection: 选中的连接
//
// URL亲和性机制：
//   - 如果是Range请求，优先使用之前为该URL分配的隧道
//   - 如果之前的隧道不可用，重新选择并更新映射
//   - 非Range请求不使用亲和性，直接按策略选择
func (lb *LoadBalancer) SelectWithAffinity(url string, rangeHeader string, requestSize int64, isStreaming bool) *TunnelConnection {
	// 🔥🔥🔥 Range请求亲和性：同一个文件的多个Range请求使用同一个隧道
	if url != "" && rangeHeader != "" {
		// 尝试从亲和性映射中获取之前使用的隧道
		lb.affinityMutex.RLock()
		affinity := lb.urlAffinity[url]
		lb.affinityMutex.RUnlock()

		if affinity != nil {
			// 检查隧道是否仍然健康
			affinity.mutex.RLock()
			isHealthy := affinity.isHealthy
			activeReqs := affinity.activeRequests
			affinity.mutex.RUnlock()

			if isHealthy {
				log.Printf("✅ [URL亲和性] Range请求复用隧道: url=%s, connID=%s, 活跃=%d",
					url, affinity.id, activeReqs)
				return affinity
			} else {
				// 隧道不健康，清理映射
				lb.affinityMutex.Lock()
				delete(lb.urlAffinity, url)
				lb.affinityMutex.Unlock()
				log.Printf("⚠️ [URL亲和性] 隧道不健康，重新选择: url=%s, 旧connID=%s",
					url, affinity.id)
			}
		}

		// 没有亲和性映射或隧道不可用，选择新的隧道
		var selected *TunnelConnection
		switch lb.strategy {
		case RoundRobin:
			selected = lb.selectRoundRobin()
		case LeastConnections:
			selected = lb.selectLeastConnections()
		case SmartSelection:
			selected = lb.selectSmart(requestSize, isStreaming)
		default:
			selected = lb.selectSmart(requestSize, isStreaming)
		}

		// 建立新的亲和性映射
		if selected != nil {
			lb.affinityMutex.Lock()
			lb.urlAffinity[url] = selected
			lb.affinityMutex.Unlock()
			log.Printf("🎯 [URL亲和性] Range请求建立映射: url=%s → connID=%s",
				url, selected.id)
		}

		return selected
	}

	// 非Range请求，按正常策略选择
	switch lb.strategy {
	case RoundRobin:
		return lb.selectRoundRobin()
	case LeastConnections:
		return lb.selectLeastConnections()
	case SmartSelection:
		return lb.selectSmart(requestSize, isStreaming)
	default:
		return lb.selectSmart(requestSize, isStreaming)
	}
}

// selectRoundRobin 轮询策略（独占模式：只选择空闲连接）
func (lb *LoadBalancer) selectRoundRobin() *TunnelConnection {
	lb.pool.mutex.RLock()
	defer lb.pool.mutex.RUnlock()

	if len(lb.pool.connections) == 0 {
		return nil
	}

	// 🔒 只选择健康且空闲的连接（activeRequests == 0）
	idleConns := make([]*TunnelConnection, 0)
	for _, conn := range lb.pool.connections {
		conn.mutex.RLock()
		isHealthy := conn.isHealthy
		conn.mutex.RUnlock()

		if isHealthy && conn.IsIdle() {
			idleConns = append(idleConns, conn)
		}
	}

	if len(idleConns) == 0 {
		log.Printf("⚠️ [独占模式] 没有空闲连接可用，所有连接都在处理请求")
		return nil
	}

	// 轮询选择空闲连接
	index := int(atomic.AddInt32(&lb.roundRobinIndex, 1)) % len(idleConns)
	return idleConns[index]
}

// selectLeastConnections 最少连接数策略（独占模式：只选择空闲连接）
func (lb *LoadBalancer) selectLeastConnections() *TunnelConnection {
	lb.pool.mutex.RLock()
	defer lb.pool.mutex.RUnlock()

	if len(lb.pool.connections) == 0 {
		return nil
	}

	// 🔒 独占模式：只选择空闲连接（activeRequests == 0）
	var selected *TunnelConnection

	for _, conn := range lb.pool.connections {
		conn.mutex.RLock()
		isHealthy := conn.isHealthy
		conn.mutex.RUnlock()

		if !isHealthy {
			continue
		}

		// 只选择完全空闲的连接
		if conn.IsIdle() {
			selected = conn
			break // 找到第一个空闲连接即可
		}
	}

	if selected == nil {
		log.Printf("⚠️ [独占模式] 没有空闲连接可用，所有连接都在处理请求")
	}

	return selected
}

// selectSmart 智能选择策略（根据请求大小和类型动态选择）
func (lb *LoadBalancer) selectSmart(requestSize int64, isStreaming bool) *TunnelConnection {
	lb.pool.mutex.RLock()
	defer lb.pool.mutex.RUnlock()

	if len(lb.pool.connections) == 0 {
		return nil
	}

	// 🔥 优化1：小请求（<1MB）→ 共享模式（立即响应）
	if requestSize < 1*1024*1024 && !isStreaming {
		selected := lb.selectLeastBusy()
		// 只在找到空闲连接时打印日志（减少噪音）
		if selected != nil && selected.IsIdle() && requestSize > 50*1024 {
			// 只记录>50KB的小请求（跳过CSS/JS等琐碎请求）
			log.Printf("✅ [小请求-共享] 立即响应: connID=%s, 大小=%.1fKB",
				selected.id, float64(requestSize)/1024)
		}
		return selected
	}

	// 🔥🔥🔥 优化2：大请求（>10MB）或流式传输 → 使用Round Robin选择空闲连接
	// 关键修复：避免所有大请求都路由到同一个连接
	if requestSize > lb.largeFileThreshold || isStreaming {
		// 使用Round Robin从不同位置开始查找空闲连接
		startIndex := int(atomic.AddInt32(&lb.roundRobinIndex, 1)) % len(lb.pool.connections)
		if startIndex < 0 {
			startIndex = -startIndex
		}

		for i := 0; i < len(lb.pool.connections); i++ {
			index := (startIndex + i) % len(lb.pool.connections)
			conn := lb.pool.connections[index]

			conn.mutex.RLock()
			isHealthy := conn.isHealthy
			conn.mutex.RUnlock()

			if isHealthy && conn.IsIdle() {
				log.Printf("✅ [大请求-独占] 使用空闲连接: connID=%s, 大小=%.2fMB",
					conn.id, float64(requestSize)/(1024*1024))
				return conn
			}
		}
		// 大请求没有空闲连接，返回nil（需要等待）
		return nil
	}

	// 🔥🔥🔥 优化3：中等请求（1-10MB）→ 优先空闲（使用Round Robin），否则共享
	// 使用Round Robin从不同位置开始查找空闲连接
	startIndex := int(atomic.AddInt32(&lb.roundRobinIndex, 1)) % len(lb.pool.connections)
	if startIndex < 0 {
		startIndex = -startIndex
	}

	for i := 0; i < len(lb.pool.connections); i++ {
		index := (startIndex + i) % len(lb.pool.connections)
		conn := lb.pool.connections[index]

		conn.mutex.RLock()
		isHealthy := conn.isHealthy
		conn.mutex.RUnlock()

		if isHealthy && conn.IsIdle() {
			log.Printf("✅ [中等请求-优先空闲] 使用空闲连接: connID=%s, 大小=%.2fMB",
				conn.id, float64(requestSize)/(1024*1024))
			return conn
		}
	}

	// 没有空闲连接，降级到共享模式
	return lb.selectLeastBusy()
}

// selectLeastBusy 选择负载最轻的连接（不要求空闲）
// 🔥 关键优化：使用Round Robin避免总是选择第一个连接
func (lb *LoadBalancer) selectLeastBusy() *TunnelConnection {
	// 注意：调用方已经持有锁，不需要再次加锁

	if len(lb.pool.connections) == 0 {
		return nil
	}

	// 🔥🔥🔥 关键修复：使用Round Robin轮询，避免总是返回第一个连接
	// 从上次选择的位置开始，遍历所有连接
	startIndex := int(atomic.AddInt32(&lb.roundRobinIndex, 1)) % len(lb.pool.connections)
	if startIndex < 0 {
		startIndex = -startIndex
	}

	var selected *TunnelConnection
	minActiveRequests := int32(1000000) // 初始化为一个很大的值

	// 🔥 遍历所有连接，找到负载最轻的（不是第一个空闲的）
	for i := 0; i < len(lb.pool.connections); i++ {
		index := (startIndex + i) % len(lb.pool.connections)
		conn := lb.pool.connections[index]

		conn.mutex.RLock()
		isHealthy := conn.isHealthy
		conn.mutex.RUnlock()

		if !isHealthy {
			continue
		}

		activeReqs := atomic.LoadInt32(&conn.activeRequests)

		// 选择活跃请求数最少的连接
		if activeReqs < minActiveRequests {
			minActiveRequests = activeReqs
			selected = conn
		}

		// 🔥 找到完全空闲的连接，优先使用
		if activeReqs == 0 {
			break // 找到空闲连接，立即使用
		}
	}

	// 🔥 商业级日志：只在负载较高或调试时打印
	if selected != nil && minActiveRequests >= 3 {
		log.Printf("⚠️ [负载均衡] 连接负载较高: connID=%s, 活跃请求=%d",
			selected.id, minActiveRequests)
	} else if selected == nil {
		log.Printf("❌ [负载均衡] 没有健康连接可用")
	} else if minActiveRequests == 0 {
		// 找到空闲连接，静默返回（减少日志噪音）
	} else {
		// 选择了有负载的连接，记录日志（用于调试）
		log.Printf("📊 [负载均衡] 选择最空闲连接: connID=%s, 活跃请求=%d",
			selected.id, minActiveRequests)
	}

	return selected
}

// ❌ selectIdleOnly已删除（未使用）

// SetStrategy 设置负载均衡策略
func (lb *LoadBalancer) SetStrategy(strategy BalancingStrategy) {
	lb.strategy = strategy
	log.Printf("🔄 更新负载均衡策略: %v", strategy)
}

// SetLargeFileThreshold 设置大文件阈值
func (lb *LoadBalancer) SetLargeFileThreshold(threshold int64) {
	lb.largeFileThreshold = threshold
	log.Printf("🔄 更新大文件阈值: %d bytes", threshold)
}

// cleanupURLAffinity 定期清理过期的URL亲和性映射
// 清理策略：
//   - 每5分钟运行一次
//   - 删除映射到不健康隧道的URL
//   - 保留映射到健康隧道的URL（即使很久没用，大文件下载可能需要很长时间）
func (lb *LoadBalancer) cleanupURLAffinity(stopChan <-chan struct{}) {
	ticker := time.NewTicker(5 * time.Minute) // 每5分钟清理一次
	defer ticker.Stop()

	log.Printf("🧹 [URL亲和性] 清理协程已启动，清理周期: 5分钟")

	for {
		select {
		case <-ticker.C:
			lb.affinityMutex.Lock()

			cleaned := 0
			total := len(lb.urlAffinity)

			// 遍历所有亲和性映射，删除不健康的隧道
			for url, conn := range lb.urlAffinity {
				conn.mutex.RLock()
				isHealthy := conn.isHealthy
				conn.mutex.RUnlock()

				if !isHealthy {
					delete(lb.urlAffinity, url)
					cleaned++
					log.Printf("🧹 [URL亲和性] 清理不健康映射: url=%s, connID=%s",
						url, conn.id)
				}
			}

			lb.affinityMutex.Unlock()

			if cleaned > 0 {
				log.Printf("🧹 [URL亲和性] 清理完成: 清理=%d, 保留=%d, 总计=%d",
					cleaned, total-cleaned, total)
			}

		case <-stopChan:
			log.Printf("🛑 [URL亲和性] 清理协程已停止")
			return
		}
	}
}
